<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>K Sprite Sheet</title>
	<link href="tuts/index.css" rel="stylesheet" type="text/css">
</head>
	
<body">
<article>
<header>
<h1>K.SpriteSheet</h1>
<canvas id="canvas" width="770" height="480"></canvas>
<p>Example how to use K.SpriteSheet</p>
</header>
<section>
<p>SpriteSheet is commonly use to animate character in games</p>
</section>
<section>
	<h2>The SpriteSheet</h2></header>
	<p>SpriteSheet is an animation by rendering bitmap frame by frame from a (big?) image. Each frame copy an area of the image to canvas (context).</p>
	<p>Some engines using a fixed renctangle for all frames, but I found many sprite-images having difference area. Some others also need a mask to filter area. This engine will support the best balance by by supporting difference area but not overlapping rectangles. It's require to set difference rectangle data for each frame.</p>
	<p>So we create some class:</p>
	<li>SpriteSheet</li>
	<li>SheetAnimation, to support the frame by frame SpriteSheet animation</li>
	<li>ImageSource, to support Sprite drawing</li>
	<h2>The ImageSource</h2>
	<p>Actually we already use it in <href url="example e02_sprite.html">example e02_sprite.html</href> but it's ok to review it. The ImageSource stores:</p>
	<li>The name of the object, of course.</li>
	<li>Position x in source image</li>
	<li>Position y in source image</li>
	<li>The rectangle's width in source image</li>
	<li>The rectangle's height in source image</li>
	<li>Offset x in screen</li>
	<li>Offset y in sreen</li>
	<p>To create an ImageSource you can type: var imgSource = new K.ImageSource(name, image, x, y, w, h, offsetX, offsetY)</p>
	<h2>The SheetAnimation</h2>
	<p>SheetAnimation need to store animation data for SpriteSheet, whick containing:</p>
	<li>The name of the object, of course.</li>
	<li>flip, if true the renderer will flipping the image</li>
	<li>start index of the animationframe</li>
	<li>end index of the animation frames</li>
	<li>loop, if true the animation will looping untill you stop it. If false, SpriteSheet will calling choose next frame or animationEnd() if not exist</li>
	<li>interval, the time interval between frames</li>
	<li>previous animation name</li>
	<li>nest animation name</li>
	<p>To create SheetAnimation use the syntax: var sheetAnimation = new KSheetAnimation(name, flip, start, end, loop, interval, prevAnim, nextAnim)</p>
	<h2>SheetData</h2>
	<p>SheetData is a class to store SpriteSheet's data, which containing:</p>
	<li>The image</li>
	<li>Array of frames</li>
	<li>Collection of animation</li>
	<p>To create Sheetdata, just use: var sheetData = new K.SheetData(theName, theImage)</p>
	<p>After that, you can add animation, without creating K.SheetAnimation but directly using the method:</p>
	<p>sheetData.addAnimation(animationName, flip, start, end, loop, interval, prevAnim, nextAnim)</p>
	<p>Next you only have to update the SpriteSheet's frame(). The engine will do the rest, except on "endAnimation". The engine will create or update ImageSource based on the SpriteSheet's property: currentFrame. If you want to it manualy, there are two methods in SheetData: </p>
	<li>createImageSource(currentFrame)</li>
	<li>updateImageSource(imageSource, currentFrame)</li>
	<h1>The Source Code</h2>
	<p></p>
	<h3>Initialize the engine</h3>
	<textarea class="ta100" readonly>
var cvs = document.getElementById("canvas");
K.stage.originWidth = cvs.width;
K.stage.originHeight = cvs.height;
K.init(cvs);
	</textarea>
	<p></p>
	<h3>Initialize the variables and mouse-handler</h3>
	<textarea class="ta200" readonly>
var sheet = new K.SheetData("knight");
//name, flip, start, end, loop, delay, prevAnim, nextAnim
sheet.addAnimation("walk_backward", false, 0, 5, true, 200, null, null);

var actors = [];

var actorClick = function(e){
	console.log(e.target.name + " click");
	e.target.y -= 40;
};
	</textarea>
	<p></p>
	
	<h3>Initliatze application</h3>
	<textarea class="ta400" readonly>
function init(){
	var i, o;
	/*
	** Create rectangles for each frames:
	** The image source having 6 pose each size 94 x 126 pixels
	** Add it to SheetData.frames
	*/
	for (i = 0; i < 6; i++) {
		o = new K.Rectangle(i * 94, 0, 94, 126);
		o.offsetX = -94/2;
		o.offsetY = -90;
		sheet.frames.push(o);
	}
	/*
	** Create The SpriteSheet
	** /// also add event-listener
	*/
	for (i = 0; i < 7; i++) {
		o = new K.SpriteSheet("sprite_" + i, i * 100 + 60, 300, sheet, "walk_backward", 0);
		o.dirty = true;
		K.stage.addChild(o);
		actors.push(o);
		o.addEventListener(K.Events.CLICK, actorClick);
	}
	/*
	** start the loop
	*/
	step();
	K.EventManager.start();
};
	</textarea>
	<p></p>
	<h3>The Loop</h3>
	<textarea class="ta300" readonly>
function step(){	
	var xx, yy;
	for (var i = 0; i < actors.length; i++) {
		xx = actors[i].x + 0.4;
		yy = actors[i].y;
		if (xx > 680) xx = - 50;
		if (yy < 400) yy = Math.min(400, yy + 2);
		actors[i].x = xx;
		actors[i].y = yy;
		actors[i].updateFrame();
	}
	// Ordervthe engine to render:
	K.render();
	// Call next frame:
	window.requestAnimationFrame(step, 1000/30);
}
	</textarea>
	<p></p>
	
	<h2>The whole code</h2>
	<textarea class="ta300" readonly>
var cvs = document.getElementById("canvas");
K.stage.originWidth = cvs.width;
K.stage.originHeight = cvs.height;
K.init(cvs);
var sheet = new K.SheetData("knight");
//name, flip, start, end, loop, delay, prevAnim, nextAnim
sheet.addAnimation("walk_backward", false, 0, 5, true, 200, null, null);
var actors = [];
var actorClick = function(e){
	console.log(e.target.name + " click");
	e.target.y -= 40;
};
function step(){	

	var xx, yy;
	for (var i = 0; i < actors.length; i++) {
		xx = actors[i].x + 0.4;
		yy = actors[i].y;
		if (xx > 680) xx = - 50;
		if (yy < 400) yy = Math.min(400, yy + 2);
		actors[i].x = xx;
		actors[i].y = yy;
		actors[i].updateFrame();
	}

	K.stage.updateMatrix();
	
	K.context.fillRect(0, 0, K.canvas.width, K.canvas.height);
	K.stage.paint(K.context);
	K.updateTime();
	
	window.requestAnimationFrame(step, 1000/30);
}
function init(){
	var i, o;
	for (i = 0; i < 6; i++) {
		o = new K.Rectangle(i * 94, 0, 94, 126);
		o.offsetX = -94/2;
		o.offsetY = -90;
		sheet.frames.push(o);
	}
	for (i = 0; i < 7; i++) {
		o = new K.SpriteSheet("sprite_" + i, i * 100 + 60, 300, sheet, "walk_backward", 0);
		o.dirty = true;
		K.stage.addChild(o);
		actors.push(o);
		o.addEventListener(K.Events.CLICK, actorClick);
	}
	step();
	K.EventManager.start();
};
sheet.image.onload = init();
sheet.image.src = "res/abobo_walk_backward_94x126x6.png";
	</textarea>
<p>	That's all. </p>
</article>

	<script src="../js/K.js"></script>
	<script>
	var cvs = document.getElementById("canvas");
	K.stage.originWidth = cvs.width;
	K.stage.originHeight = cvs.height;
	K.init(cvs);
	
	var sheet = new K.SheetData("knight");
	//name, flip, start, end, loop, delay, prevAnim, nextAnim
	sheet.addAnimation("walk_backward", false, 0, 5, true, 200, null, null);
	
	var actors = [];
	
	function step(){	
	
		var xx, yy;
		for (var i = 0; i < actors.length; i++) {
			xx = actors[i].x + 0.4;
			yy = actors[i].y;
			if (xx > 800) xx = - 50;
			if (yy < 400) yy = Math.min(400, yy + 2);
			actors[i].x = xx;
			actors[i].y = yy;
			actors[i].updateFrame();
		}
	
		K.render();
		
		window.requestAnimationFrame(step, 1000/30);
	}
	
	var actorClick = function(e){
		console.log(e.target.name + " click");
		e.target.y -= 40;
	};
	
	function init(){
		var i, o;
		for (i = 0; i < 6; i++) {
			o = new K.Rectangle(i * 94, 0, 94, 126);
			o.offsetX = -94/2;
			o.offsetY = -90;
			sheet.frames.push(o);
		}
		for (i = 0; i < 7; i++) {
			o = new K.SpriteSheet("sprite_" + i, i * 100 + 60, 300, sheet, "walk_backward", 0);
			o.dirty = true;
			K.stage.addChild(o);
			actors.push(o);
			o.addEventListener(K.Events.CLICK, actorClick);
		}
		step();
		K.EventManager.start();
	};
	
	sheet.image.onload = init();
	sheet.image.src = "res/abobo_walk_backward_94x126x6.png";
	</script>
</body>
</html>
